63

jQuery(document).ready(function() {
    //workers pueden tener 4 estados: libre, ensamblando, en-cola, y en-horno
    var workers;
    var maquinas;
    var eventos;
    var cola;
    var reloj;
    var piezasTerminadas;
    var nroSimulacion = 0;
    $('#Simular').click(function() {
        $('.progress').show();
        $('#vector').html('');
		$('#vector').remove();
        workers = new Array();
        maquinas = new Array();
        eventos = new Array({tipo: 'inicio', tiempo: 0, eventoAsoc: null, hora: 0, worker: {name: undefined}});
        cola = new Array();
        reloj = 0;
        piezasTerminadas = new Array();

        var cantWorkers = parseFloat($('input[name="workers"]').val());
        var cantMaquinas = parseFloat($('input[name="maquinas"]').val());
        var demanda = parseFloat($('input[name="demanda"]').val());


        for (i = 1; i <= cantWorkers; i++) {
            workers.push({name: 'worker' + i, status: 'libre'});
        }


        workers.getSiguienteWorkerLibrePonerEnCola = function()
        {
            for (i = 0; i < this.length; i++)
            {
                if (this[i].status == 'libre') {
                    this[i].status = 'en-cola';
                    return this[i];
                }
            }

        };
        workers.getSiguienteWorkerLibre = function()
        {
            for (i = 0; i < this.length; i++)
            {
                if (this[i].status == 'libre') {
                    return this[i];
                }
            }

        };
        workers.setWorker = function(worker) {
            for (i = 0; i < this.length; i++)
            {
                if (this[i].name == worker.name) {
                    this[i] = worker;
                }
            }
        };
        workers.hayLibre = function() {
            for (i = 0; i < this.length; i++)
            {
                if (this[i].status == 'libre') {
                    return true;
                }
            }
            return false;
        };

        for (var i = 1; i <= cantMaquinas; i++) {
            //las maquinas pueden tener 2 estados: libre, ocupado
            maquinas.push({name: 'horno' + i, status: 'libre'});
        }

        maquinas.getSiguienteMaquinaLibre = function() {
            for (i = 0; i < this.length; i++)
            {
                if (this[i].status == 'libre') {
                    return this[i];
                }
            }
        };
        maquinas.hayLibre = function() {
            for (i = 0; i < this.length; i++)
            {
                if (this[i].status == 'libre') {
                    return true;
                }
            }
            return false;
        };
        maquinas.setMaquina = function(maquina) {
            for (i = 0; i < this.length; i++)
            {
                if (this[i].name == maquina.name) {
                    this[i] = maquina;
                }
            }
        };
        eventos.getNext = function() {
            var mayor = this[0];
            for (i = 0; i < this.length; i++)
            {
                if (this[i + 1] != undefined && this[i].hora < this[i + 1].hora) {
                    mayor = this[i + 1];
                }
            }
            return mayor;
        }
        //var tiempoFinalizacion = 16*60;//60 segundos a miliseconds


        var vectorEstado = new Array();
        var $table = $('<table id="vector" style="display:none"></table>');
        var $line = $("<tr></tr>");
        $line.append($("<td>Reloj</td>"));
        $line.append($("<td>Evento actual</td>"));
        $line.append($("<td>Evento proximo</td>"));
        $line.append($("<td>Tiempo</td>"));
        $line.append($("<td>Proxima hora de evento</td>"));
        $line.append($("<td>Cola</td>"));
        $line.append($("<td><span class='tooltip-title' title='Moldes terminados'>Moldes</span></td>"));
        $line.append($("<td>Ganancia</td>"));
        $line.append($("<td><span class='tooltip-title' title='Costo=(Cant de trabajadores*Hora trabajada) + (CantMaquinas*dia)'>Costos</span></td>"));
        $line.append($("<td><span class='label label-success tooltip-title' title='Ganacia - Costos'>Neto</span></td>"));
        $.each(workers, function(index, worker) {
            $line.append($("<td><span class='label label-info'>Estado " + worker.name + "</span></td>"));
        });
        $.each(maquinas, function(index, maquina) {
            $line.append($("<td><span class='label label-important'>Estado " + maquina.name + "</span></td>"));
        });
        $table.append($line);

        while (true) {
            //console.log(eventos);
            var evento = eventos[0]; //del array de eventos quitamos el ultimo, que es el mas temprano segun lo ordenamos con la funcion eventos.sort(ultimoMasTemprano);

            if (evento == undefined) {
                break;
            }
            reloj = evento.hora;

            if (piezasTerminadas.length == demanda) {
                break;
            }


            //if (evento.hora > tiempoFinalizacion && evento.tipo=='finEnsamblado')//finalizamos si el tiempo del evento es mayor que el de finalizacion
            //  break;

            switch (evento.tipo) {
                case 'inicio':
                    //evento.ejecutar();//el evento dependiendo de que tipo sea debera cambiar algun estado, sumar algo, etc
                    eventoInicio(evento);//hay q ver el tema de los trabajadores como van llegando sus piezas!!!
                    break;
                case 'finAtencion':
                    //evento.ejecutar();//el evento dependiendo de que tipo sea debera cambiar algun estado, sumar algo, etc
                    eventoFinAtencion(evento);
                    break;
                case 'finEnsamblado':
                    //evento.ejecutar();//el evento dependiendo de que tipo sea debera cambiar algun estado, sumar algo, etc
                    eventoFinEnsamblado(evento);
                    break;
            }
            var $ganancia = piezasTerminadas.length * 5;
            var costoWorkers = (workers.length * (reloj / 60).toFixed(0) * 3.75);
            var dias = parseFloat((reloj / 60) / 24);
            dias = dias + 1;
            if (Math.round(dias) < dias)
                dias = Math.round(dias);
            else
                dias = Math.round(dias) - 1;
            var costoMaquinas = (maquinas.length * 80 * dias);
            var $costo = costoWorkers + costoMaquinas;

            estado = {reloj: reloj, evento: evento, proximoEvento: eventos[1], cola: cola, ganancia: $ganancia, costo: $costo, neto: ($ganancia - $costo)};
            vectorEstado.push(estado);

            /*$('.container-narrow').append('<p>Reloj:' + reloj + '</p>');
             $('.container-narrow').append('<p>Evento: <span class="' + evento.tipo + '">' + evento.tipo + '</span></p>');
             $('.container-narrow').append('<p>Cantidad en cola:' + cola.length + '</p>');
             $('.container-narrow').append('<p>-----------------------</p>');*/
            if (evento.maquina == undefined)
                evento.maquina = {name: ''};
            var $line = $("<tr></tr>");
            var label = '<span class="label label-info">Inicio</span>';
            if (evento.tipo == 'finAtencion')
                label = '<span class="label label-important">finAtencion</span>';
            if (evento.tipo == 'finEnsamblado') {
                if (evento.eventoAsoc != undefined)
                    label = '<span class="label label-warning tooltip-title" title="como no hay cola calculo su ' + evento.eventoAsoc.tipo + ', duracion:'+evento.eventoAsoc.tiempo+', hora evento:' + evento.eventoAsoc.hora + '\'">finEnsamblado</span>';
                else
                    label = '<span class="label label-warning tooltip-title" title="va a parar a la cola">finEnsamblado</span>';
            }

            var label2 = '<span class="label label-info">Inicio</span>';
            if (eventos[1].tipo == 'finAtencion')
                label2 = '<span class="label label-important">finAtencion</span>';
            if (eventos[1].tipo == 'finEnsamblado')
                label2 = '<span class="label label-warning">finEnsamblado</span>';

            $line.append($("<td></td>").html(reloj + ' min (' + (reloj / 60).toFixed(2) + 'hs)'));
            $line.append($("<td></td>").html(label + ' (' + evento.worker.name + ' ' + evento.maquina.name + ')'));
            $line.append($("<td></td>").html(label2 + '(' + eventos[1].worker.name + ')'));
            $line.append($("<td></td>").html(eventos[1].tiempo + ' min (' + (eventos[1].tiempo / 60).toFixed(2) + 'hs)'));
            $line.append($("<td></td>").html(eventos[1].hora + ' min (' + (eventos[1].hora / 60).toFixed(2) + 'hs)'));

            $line.append($("<td></td>").html('<span class="badge badge-important">' + estado.cola.length + '</span>'));
            $line.append($("<td></td>").html('<span class="badge">' + piezasTerminadas.length + '</span>'));

            $line.append($("<td></td>").html('$' + $ganancia));

            $line.append(
                    $("<td></td>").html(
                    '<span class="tooltip-title" title="(cantEnsambladores*HorasTrabajadas*3.75) + (cantHornos*diasTrabajados*80)">$' + costoWorkers + '+$' + costoMaquinas + '=' + $costo + '</span>'
                    )
                    );
            $line.append($("<td></td>").html('$' + ($ganancia - $costo)));
            $.each(workers, function(index, worker) {
                $line.append($("<td>" + worker.status + "</td>"));
            });
            $.each(maquinas, function(index, maquina) {
                $line.append($("<td>" + maquina.status + "</td>"));
            });
            $table.append($line);

            eventos.splice(0, 1);

        }

        //sumamos al reloj el tiempo


        $('.container-narrow').addClass('CSSTableGenerator');
        $('.container-narrow').append($table);
        $('#vector').fadeIn();
        $('#resultados').fadeIn();
        nroSimulacion++;

        $('#resultados ul').append('<li class="pop' + nroSimulacion + ' clickable">Simulacion <span class="badge badge-success">' + nroSimulacion + '</span> -> $' + ($ganancia - $costo) + ' en ' + (reloj / 60).toFixed(2) + 'hs</li>');
        //console.log(vectorEstado);
        $('#resultados ul li.pop' + nroSimulacion).popover({title: 'Simulacion <span class="badge badge-success">' + nroSimulacion + '</span>', html: true, content: '<strong>Ensambladores:</strong> ' + workers.length + '<br><strong>Hornos:</strong> ' + maquinas.length});
        $()
        $('.tooltip-title').tooltip();
    });



    function eventoFinAtencion(evento) {
        piezasTerminadas.push(1);
        if (cola.length > 0) {
            evento.maquina.status = 'ocupado';
            maquinas.setMaquina(evento.maquina);
            var tiempo5 = uniformGenerator(2, 4);
            var worker = cola.shift();
            worker.status = 'en-horno';
            workers.setWorker(worker);
            eventos.push({tipo: 'finAtencion',
                tiempo: tiempo5,
                hora: (reloj + tiempo5),
                maquina: evento.maquina,
                worker: worker});//fin de atencion con dist uniforme de 3 a 5 segundos (los puse asi para probar)

        } else {
            /**/
            evento.maquina.status = 'libre';
            maquinas.setMaquina(evento.maquina);
        }
        //COMO ESTA LIBRE LO TENGO Q OCUPAR!!!!
        evento.worker.status = 'ensamblando';
        workers.setWorker(evento.worker);
        var tiempo4 = uniformGenerator(25, 35);
        eventos.push({tipo: 'finEnsamblado',
            tiempo: tiempo4,
            hora: (reloj + tiempo4),
            worker: evento.worker});//finEnsamblado con dist uniforme de 2 a 3 segundos (los puse asi para probar)

        eventos.sort(ultimoMasTemprano);
    }
    function eventoFinEnsamblado(evento) {

        if (maquinas.hayLibre() == false) {
            evento.worker.status = 'en-cola';
            workers.setWorker(evento.worker);
            cola.push(evento.worker);//removemos el primer item de la cola

        } else {
            var maquinaAOcupar = maquinas.getSiguienteMaquinaLibre();

            var tiempo2 = uniformGenerator(2, 4);
            var finAt = {tipo: 'finAtencion',
                tiempo: tiempo2,
                hora: (reloj + tiempo2),
                maquina: maquinaAOcupar,
                worker: evento.worker};
            eventos.push(finAt);//fin de atencion con dist uniforme de 3 a 5 segundos (los puse asi para probar)
            evento.worker.status = 'en-horno';
            evento.eventoAsoc = finAt;

            workers.setWorker(evento.worker);
            maquinaAOcupar.status = 'ocupado';
            maquinas.setMaquina(maquinaAOcupar);

        }
        //calculo la proxima finEnsamblado SI HAY WORKER LIBRE (PORQ SI ESTA EN COLA O HORNO NO PUEDO CALCULAR SU LLEGADA)
        if (workers.hayLibre()) {
            var worker = workers.getSiguienteWorkerLibre();
            worker.status = 'ensamblando';
            workers.setWorker(worker);
            var tiempo1 = uniformGenerator(25, 35);
            eventos.push({tipo: 'finEnsamblado',
                tiempo: tiempo1,
                hora: (reloj + tiempo1),
                worker: worker});//finEnsamblado con dist uniforme de 2 a 3 segundos (los puse asi para probar)
        }
        eventos.sort(ultimoMasTemprano);//ordenamos el array por el tiempo del evento, quedando al final el mas temprano


    }
    function eventoInicio(evento) {


        //calculo la proxima finEnsamblado SI HAY WORKER LIBRE (PORQ SI ESTA EN COLA O HORNO NO PUEDO CALCULAR SU LLEGADA)
        for (var i = 0; i < workers.length; i++)
        {
            var worker = workers.getSiguienteWorkerLibre();
            //console.log(worker);
            worker.status = 'ensamblando';
            workers.setWorker(worker);
            //console.log(workers);
            var tiempo = uniformGenerator(25, 35);
            eventos.push({tipo: 'finEnsamblado',
                tiempo: tiempo,
                hora: tiempo,
                worker: worker});//finEnsamblado con dist uniforme de 2 a 3 segundos (los puse asi para probar)
        }
        eventos.sort(ultimoMasTemprano);//ordenamos el array por el tiempo del evento, quedando al final el mas temprano


    }
    function ultimoMasTemprano(a, b) {
        if (a.hora < b.hora)
            return -1;
        if (a.hora > b.hora)
            return 1;
        return 0;
    }



    function uniformGenerator(lower, upper) {
        if (arguments.length != 2) {                         // ARG_CHECK                     
            throw new SyntaxError("uniform() must be called" // ARG_CHECK
                    + " with lower and upper parameters");    // ARG_CHECK
        }                                                   // ARG_CHECK
        return Math.round(lower + Math.random() * (upper - lower));
    }

});
